///////////////////////////////////////////////////////////////////////////////
////  (c) Chaichuk AU (chaichuk@mail.ru), 								   ////
////  2004, Chelyabinsk, NTC Privodnaya Tehnika (momentum@chel.surnet.ru)  ////
///////////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
#include <time.h>

#include "../api/memtype.h"
#include "plc_io.h"

short CIO_mem [50000];
short WR_mem  [50000];
short DM_mem  [50000];
short TIM_mem [50000];
short CNT_mem [50000];

  

char* get_time_now ()
{
	time_t tod;
	static char out [100];
	
	time (&tod);
    strftime (out, sizeof (out), "%d-%m-%Y %T", localtime (&tod));	
    
    return out;
}

int memory_read (int memory_code, int start_addr, int n_items, short *buf)
{
	int bitnum 	= start_addr & 0xff;
	int addr	= start_addr >> 8;
	int i;
	
//	fprintf (stderr, "read bitnum = %d, addr = %d\n", bitnum, addr);
	
	for (i = 0; i < n_items; i++) {
		switch (memory_code) {
			case CIO_BIT:
				buf [i] = (CIO_mem [addr+i] >> bitnum) & 1;
				break;
			case CIO_WRD:
				buf [i] = CIO_mem [addr+i];				
				break;
				
			case WR_BIT:
				buf [i] = (WR_mem [addr+i] >> bitnum) & 1;
				break;
			case WR_WRD:
				buf [i] = WR_mem [addr+i];				
				break;

			case DM_BIT:
				buf [i] = (DM_mem [addr+i] >> bitnum) & 1;
				break;
			case DM_WRD:
				buf [i] = DM_mem [addr+i];				
				break;

			case TIM_WRD: // =CNT_WRD
//				fprintf (stderr, "rd bitnum = %d, addr = %d\n", bitnum, addr);
				if ((addr+i) & 0x8000) buf [i] = CNT_mem [(addr+i) & (~0x8000)];
				else buf [i] = TIM_mem [addr+i];				
				break;
		}							
	}
	delay (15);	
	return 0;
}

int memory_write (int memory_code, int start_addr, int n_items, short *buf)
{
	int bitnum 	= start_addr & 0xff;
	int addr	= start_addr >> 8;
	int i;
	
//	fprintf (stderr, "write bitnum = %d, addr = %d\n", bitnum, addr);
	
	for (i = 0; i < n_items; i++) {
		switch (memory_code) {
			case CIO_BIT:
				if (buf [i] == 1) CIO_mem [addr+i] |= (1 << bitnum);
				else CIO_mem [addr+i] &= ~(1L << bitnum);
				break;
			case CIO_WRD:
				CIO_mem [addr+i] = buf [i];				
				break;
				
			case WR_BIT:
				if (buf [i] == 1) WR_mem [addr+i] |= (1 << bitnum);
				else WR_mem [addr+i] &= ~(1L << bitnum);
				break;
			case WR_WRD:
				WR_mem [addr+i] = buf [i];				
				break;

			case DM_BIT:
				if (buf [i] == 1) DM_mem [addr+i] |= (1 << bitnum);
				else DM_mem [addr+i] &= ~(1L << bitnum);
				break;
			case DM_WRD:
				DM_mem [addr+i] = buf [i];				
				break;
		
			case TIM_WRD: // =CNT_WRD
				if ((addr+i) & 0x8000) CNT_mem [(addr+i) & (~0x8000)] = buf [i];
				else TIM_mem [addr+i] = buf [i];				
				break;
		}							
	}
	delay (15);	
	return 0;
}